#pragma once
#include <pthread.h>
#include <string>
#include <vector>
#include <unordered_map>
#include "databaseSvr.hpp"
//using std::string;
using std::cout;
using std::endl;
enum UserStatus{
  OFFLINE,
  ONLINE
};

class UserInfo{
public:
  UserInfo(int userid, const string& nickname, const string& school, const string& telnum, const string& passwd)
    :userid_(userid)
    ,nickname_(nickname)
    ,school_(school)
    ,telnum_(telnum)
    ,passwd_(passwd) {
  
    user_status_ = OFFLINE;
    tcp_socket_ = -1;
    friend_id_.clear();
   }

  UserInfo() {

  }

  ~UserInfo() {

  }

public:
  int userid_;
  string nickname_;
  string school_;
  string telnum_;
  string passwd_;

  //用户状态
  UserStatus user_status_;
  //登录的客户端对应的套接字描述符
  int tcp_socket_;
  //好友信息
  std::vector<int> friend_id_;
};

class UserManager{
public:
  UserManager() {
    user_map_.clear();
    pthread_mutex_init(&map_lock_, NULL);
    db_ = NULL;
    //开始不可以对它直接赋值,前面可能已经有东西了
    prepare_id_ = -1;
  }

  ~UserManager() {
    if (db_) {
      delete db_;
      db_ = NULL;
    }
    pthread_mutex_destroy(&map_lock_);
  }

  bool InitUserManager() {
    //连接数据库
    db_ = new DataBaseSvr();
    if (db_ == NULL) {
      std::cout << "create db_ failed" << std::endl;
      return false;
    }
    if (db_->MysqlInit() == false) {
      std::cout << "db_->MysqlInit() failed" << std::endl;
      return false;
    }
    //把数据库中的信息维护起来
    Json::Value alluer;
    if (db_->GetAllUser(&alluer) == false) {
      return false;
    }
    for (int i = 0; i < (int)alluer.size(); i++) {
      //个人信息
      UserInfo ui;
      ui.userid_ = alluer[i]["userid"].asInt();
      ui.nickname_ = alluer[i]["nickname"].asString();
      ui.school_ = alluer[i]["school"].asString();
      ui.telnum_ = alluer[i]["telnum"].asString();
      ui.passwd_ = alluer[i]["passwd"].asString();
      ui.user_status_ = OFFLINE; 
      //个人好友信息
      db_->GetFriend(ui.userid_, &ui.friend_id_); 

      //放进维护的容器中
      pthread_mutex_lock(&map_lock_);
      user_map_[ui.userid_] = ui;
      prepare_id_ = ui.userid_ + 1;
      pthread_mutex_unlock(&map_lock_);
    }

    return true;
  }
  
  //处理注册信息
  int DealRegister(const string& nickname, const string& school, const string& telnum, const string& passwd, int* userid) {
    //判断是否合法
    if (nickname.empty() || school.empty() || telnum.empty() || passwd.empty()) {
      *userid = -2;
      return -1;
    }
    
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.begin();
    while (it != user_map_.end()) {
      if (it->second.telnum_ == telnum) {
        *userid = -2;
        std::cout << "itt" << it->second.telnum_ << std::endl;
        pthread_mutex_unlock(&map_lock_);
        return -1;
      }
      it++;
    }
    //std::cout << "到这里是合法的" << std::endl;
    //没有检测到违法,注册信息加入到user_map_中
    UserInfo ui(prepare_id_, nickname, school, telnum, passwd);
    user_map_[prepare_id_] = ui;
    *userid = prepare_id_;
    prepare_id_++;
    pthread_mutex_unlock(&map_lock_);
    //将注册入户放入数据库中
    db_->InsertUser(ui.userid_, nickname, school, telnum, passwd);
    return ui.userid_;
  }

  //处理登录
  int DealLogin(const string& telnum, const string& passwd, int sockfd) {
    //判断是否为空
    //cout << "这里是用户处理登录的地方,我已经来到这里" << endl;
    if (telnum.empty() || passwd.empty()) {
      return -1;
    }
    //cout << "我不是空的"  << endl;
    //判断电话号码是否注册过
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.begin();
    while (it != user_map_.end()) {
      if (it->second.telnum_ == telnum) {
        break;
      }
      it++;
    }
    if (it == user_map_.end()) {
      pthread_mutex_unlock(&map_lock_);
      return -1;
    }
    //cout << "这个电话号码已经注册过了,可以登录" << endl;
    //走到这里,可以确定电话号码已经注册过,判断密码是否正确
    if (passwd != it->second.passwd_) {
      pthread_mutex_unlock(&map_lock_);
      return -1; 
    }
    //cout << "这个电话是正确的" << endl;
    //电话号码与密码都正确,状态改为在线
    it->second.user_status_ = ONLINE;
    it->second.tcp_socket_ = sockfd;
    pthread_mutex_unlock(&map_lock_);
    //cout << "我要返回了" << endl;
    return it->second.userid_;
  }

  int IsLogin(int userid) {
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.find(userid);
    if (it == user_map_.end()) {
      pthread_mutex_unlock(&map_lock_);
      return -1;
    }
      pthread_mutex_unlock(&map_lock_);

    return it->second.user_status_;
  }

  int IsLogin(const string& telnum, UserInfo* ui) {
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.begin();
    while (it != user_map_.end()) {
      if (it->second.telnum_ == telnum) {
        break;
      }
      it++;
    }
    if (it == user_map_.end()) {
      pthread_mutex_unlock(&map_lock_);
      return -1;
    }
    *ui = it->second;
    if(it->second.user_status_ == OFFLINE){
        pthread_mutex_unlock(&map_lock_);
        return OFFLINE;                                          
    }
    pthread_mutex_unlock(&map_lock_);
    return ONLINE;
  }
  bool GetUserInfo(int userid, UserInfo* ui) {
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.find(userid);
    if (it == user_map_.end()) {
      pthread_mutex_unlock(&map_lock_);
      return false;
    }
    *ui = it->second;
    pthread_mutex_unlock(&map_lock_);
    return true;
    
  }

  bool GetFriends(int userid, std::vector<int>* finfo) {
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.find(userid);
    if (it == user_map_.end()) {
      pthread_mutex_unlock(&map_lock_);
      return false;
    }
      pthread_mutex_unlock(&map_lock_);
    *finfo = it->second.friend_id_;
    return true;
  }

  void SetFriend(int userid1, int userid2) {
    //把对方放到user_map_中
    pthread_mutex_lock(&map_lock_);
    auto it = user_map_.find(userid1);
    it->second.friend_id_.push_back(userid2);
    it = user_map_.find(userid2);
    it->second.friend_id_.push_back(userid1);
    pthread_mutex_unlock(&map_lock_);
    //插入到数据库中
    db_->InsertFriend(userid1, userid2);
    db_->InsertFriend(userid2, userid1);
  }

  void SetUserOffLine(int sockfd){
            pthread_mutex_lock(&map_lock_);
            auto iter = user_map_.begin();
            while(iter != user_map_.end()){
             if(iter->second.tcp_socket_ == sockfd){
                    iter->second.user_status_ = OFFLINE;
                }
                iter++;
            }
            pthread_mutex_unlock(&map_lock_);
  }
private:
  //把不同的用户信息组织起来
  std::unordered_map<int, UserInfo> user_map_;
  pthread_mutex_t map_lock_;

  //对于注册的用户分配的id
  int prepare_id_;

  //操作数据库的指针
  DataBaseSvr* db_;
};
